import React from "react";
import {Button as AntdButton, Card, Form as AntdForm, Input} from 'antd';
import {
    renderItems,
    VJsonComponent,
    VJsonComponentBase,
} from "../../factory";
import _ from 'lodash'
import {ColProps} from "antd/lib/grid/col";
import {FormLayout} from "antd/lib/form/Form";
import {SizeType} from "antd/lib/config-provider/SizeContext";
import {FormInstance} from "antd/lib/form/hooks/useForm";
import {RefObject} from "react";
import {Observer} from 'mobx-react';
import {NamePath} from "rc-field-form/es/interface";
import {apply, deepTraverObject} from "../..";
import {transaction} from "mobx";

export interface FormVJsonProp {
    /**
     * 是否可见
     */
    visible?: boolean
    debug?: string
    component?: false | string | React.FC<any> | React.ComponentClass<any>
    labelCol?: ColProps
    wrapperCol?: ColProps
    layout?: FormLayout
    size?: SizeType
    items: any[]
}

export interface PageState extends FormVJsonProp {

}

@VJsonComponent({
    view: 'form'
})
export default class Form extends VJsonComponentBase<FormVJsonProp, PageState> {
    static defaultProps = {
        visible: true,
        items: [],
    }

    formRef: RefObject<FormInstance> = React.createRef();

    constructor(props: any) {
        super(props);

        _.defaults(
            this.props.vjson,
            Form.defaultProps
        )
    }

    debugInfo(): JSX.Element {
        return (
            <Observer key={_.uniqueId('_')}>
                {
                    () => this.props.vjson.debug ? <Card>
                        <pre>{JSON.stringify(this.props.$context.scopeInstance[this.props.vjson.debug], null, ' ')}</pre>
                    </Card> : null
                }
            </Observer>
        )
    }

    validateFields(): undefined | Promise<any> {
        if (!this.formRef.current) {
            return
        }
        return this.formRef.current.validateFields()
    }

    scrollToField(bind: string, option?: ScrollOptions) {
        if (!this.formRef.current) {
            return
        }

        return this.formRef.current.scrollToField(bind, option)
    }

    /**
     * 清空表单
     * @param fields 需要额外被清空的字段
     * @param omit 需要被排除的字段
     */
    resetFields(fields: string[] = [], omit: string[] = []) {

        transaction(() => {
            if (!this.formRef.current) {
                return
            }

            const scope = this.props.$context.scopeInstance
            const hierarchyEntity = this.formRef.current.getFieldsValue()
            _.forEach(fields, key => {
                _.set(scope, key, '')
            })
            _.forOwn(hierarchyEntity, (value, key) => {
                if (_.includes(omit, key)) {
                    return
                }
                _.set(scope, key, '')
            })
        })
    }


    render() {
        if (!this.props.vjson.visible) {
            return null
        }

        return (
            // @ts-ignore
            <AntdForm key={this.key} view_id={this.key} aria-roledescription={this.view}
                      ref={this.formRef}
                      component={this.props.vjson.component}
                      labelCol={this.props.vjson.labelCol}
                      className={this.props.vjson.className}
                      wrapperCol={this.props.vjson.wrapperCol}
                      layout={this.props.vjson.layout}
                      size={apply(this, this.props.vjson.size)}
                      scrollToFirstError={true}
                      onFieldsChange={(changedFields, allFields) => {
                          // 编辑框编辑后会通知到这个方法
                          _.each(changedFields, f => {
                              f.value = _.get(this.props.$context.scopeInstance, f.name.toString())
                          })
                      }}
            >
                {
                    ...renderItems(this, this.props.vjson.items, {$formRef: this.formRef})
                }
                {
                    this.debugInfo()
                }
            </AntdForm>
        )
    }
}
